#pragma once
#include <unistd.h>
#include <pthread.h>
#include <queue>
#include <vector>
#include "Task.h"

const int MAX_THREAD = 10;
const int MIN_THREAD = 0;
const int INC_THREAD = 2;
const int DEC_THREAD = 2;
const int QUEUE_SIZE = 10;

template <class T>
class ThreadPool
{
public:
    ThreadPool(int max = MAX_THREAD, int min = MIN_THREAD, int size = QUEUE_SIZE)
        : _max(max),
          _liveNum(max),
          _min(min),
          _taskSize(size)
    {
        _threadIDs.resize(max, 0);
        // 创建管理线程
        pthread_create(&_managerID, nullptr, manager, (void *)this);
        // 创建执行任务线程
        for (int i = 0; i < max; ++i)
        {
            pthread_create(&_threadIDs[i], nullptr, worker, (void *)this);
            std::cout << _threadIDs[i] << " create" << std::endl;
        }
        // 初始化锁和条件变量
        pthread_mutex_init(&_poolMutex, nullptr);
        pthread_mutex_init(&_busyMutex, nullptr);
        pthread_cond_init(&_full, nullptr);
        pthread_cond_init(&_empty, nullptr);
    }
    void AddTask(T *task)
    {
        pthread_mutex_lock(&_poolMutex);
        std::cout << "add:" << task->_num << std::endl;
        // 满了
        while (_taskQ.size() == _taskSize && !_isStop)
        {
            pthread_cond_wait(&_full, &_poolMutex);
        }
        if (_isStop)
        {
            pthread_mutex_unlock(&_poolMutex);
            return;
        }
        // 放任务
        _taskQ.push(task);
        // 唤醒消费者
        pthread_cond_signal(&_empty);
        pthread_mutex_unlock(&_poolMutex);
    }
    int getBusyThreadNum()
    {
        pthread_mutex_lock(&_poolMutex);
        int busyNum = _busyNum;
        pthread_mutex_unlock(&_poolMutex);
        return busyNum;
    }
    int getAliveThreadNum()
    {
        pthread_mutex_lock(&_poolMutex);
        int liveNum = _liveNum;
        pthread_mutex_unlock(&_poolMutex);
        return _liveNum;
    }
    ~ThreadPool()
    {
        // 关闭线程池
        _isStop = true;
        // 管理线程销毁
        std::cout << "manager thread join" << std::endl;
        pthread_join(_managerID, nullptr);
        // 唤醒阻塞的消费者线程
        for (int i = 0; i < _max; ++i)
        {
            if (_threadIDs[i])
                pthread_cond_signal(&_empty);
        }
        for (auto e : _joinThreadIDs)
        {
            pthread_join(e, nullptr);
        }
        // for (auto &e : _threadIDs)
        // {
        //     if (e)
        //     {
        //         pthread_join(e, nullptr);
        //         e = 0;
        //     }
        // }
        std::cout << "join threads num:" << _joinThreadIDs.size() << std::endl;
        // 销毁锁和条件变量
        pthread_mutex_destroy(&_poolMutex);
        pthread_mutex_destroy(&_busyMutex);
        pthread_cond_destroy(&_full);
        pthread_cond_destroy(&_empty);
        for (auto e : _threadIDs)
        {
            std::cout << e << std::endl;
        }
    }

private:
    bool check()
    {
        for (auto e : _threadIDs)
        {
            if (e)
                return true;
        }
        return false;
    }
    static void *manager(void *arg)
    {
        ThreadPool *pool = static_cast<ThreadPool *>(arg);
        while (!pool->_isStop)
        {
            sleep(3);
            // 取出当前pool线程数，任务数
            pthread_mutex_lock(&pool->_poolMutex);
            int queueSize = pool->_taskQ.size();
            int liveNum = pool->_liveNum;
            pthread_mutex_unlock(&pool->_poolMutex);
            // 取出忙线程数
            pthread_mutex_lock(&pool->_busyMutex);
            int busyNum = pool->_busyNum;
            pthread_mutex_unlock(&pool->_busyMutex);
            // 增加线程  任务数量大于存活线程数 添加两个
            if (queueSize > liveNum && liveNum <= pool->_max)
            {
                int count = 0;
                pthread_mutex_lock(&pool->_poolMutex);
                for (int i = 0; i < pool->_max && count < INC_THREAD && pool->_liveNum < pool->_max; ++i)
                {
                    if (pool->_threadIDs[i] != 0)
                    {
                        pthread_create(&pool->_threadIDs[i], nullptr, worker, (void *)pool);
                        ++count;
                        pool->_liveNum++;
                    }
                }
                pthread_mutex_unlock(&pool->_poolMutex);
            }
            // 销毁线程  忙线程*2 < 存活线程
            if (busyNum * 2 < liveNum && liveNum > pool->_min)
            {
                pthread_mutex_lock(&pool->_poolMutex);
                pool->_exitNum = DEC_THREAD;
                pthread_mutex_unlock(&pool->_poolMutex);
                // 让工作线程自杀
                for (int i = 0; i < DEC_THREAD; ++i)
                {
                    pthread_cond_signal(&pool->_empty);
                }
            }
            std::cout << "busy:" << busyNum << std::endl;
            std::cout << "live:" << liveNum << std::endl;
        }
    }
    static void *worker(void *arg)
    {
        ThreadPool *pool = static_cast<ThreadPool *>(arg);
        while (!pool->_isStop)
        {
            pthread_mutex_lock(&pool->_poolMutex);
            while (pool->_taskQ.empty() && !pool->_isStop)
            {
                // 睡眠
                pthread_cond_wait(&pool->_empty, &pool->_poolMutex);
                if (pool->_isStop)
                    goto EXIT;
                // 判断是不是销毁线程
                if (pool->_exitNum > 0)
                {
                    pool->_exitNum--;
                    if (pool->_liveNum > pool->_min)
                    {
                        pool->_liveNum--;
                        pthread_mutex_unlock(&pool->_poolMutex);
                        pool->ThreadExit();
                    }
                }
            }
        EXIT:
            // 判断线程池是否关闭
            if (pool->_isStop)
            {
                pool->_liveNum--;
                pthread_mutex_unlock(&pool->_poolMutex);
                pool->ThreadExit();
            }
            // 取任务
            T *task = pool->_taskQ.front();
            pool->_taskQ.pop();
            pthread_mutex_unlock(&pool->_poolMutex);
            // 唤醒生产者
            pthread_cond_signal(&pool->_full);

            // 忙线程数加1
            std::cout << "thread " << pthread_self() << " start working ..." << std::endl;
            pthread_mutex_lock(&pool->_busyMutex);
            pool->_busyNum++;
            pthread_mutex_unlock(&pool->_busyMutex);
            // 执行任务
            task->Run();
            delete task;
            task = nullptr;
            // 忙线程数减1
            std::cout << "thread " << pthread_self() << " end working ..." << std::endl;
            pthread_mutex_lock(&pool->_busyMutex);
            pool->_busyNum--;
            pthread_mutex_unlock(&pool->_busyMutex);
        }
        pthread_mutex_lock(&pool->_poolMutex);
        pool->_liveNum--;
        pthread_mutex_unlock(&pool->_poolMutex);
        pool->ThreadExit();
    }
    void ThreadExit()
    {
        pthread_t tid = pthread_self();
        _joinThreadIDs.push_back(tid);
        for (auto &id : _threadIDs)
        {
            if (tid == id)
            {
                id = 0;
                std::cout << "ThreadExit() called, " << tid << " exiting ..." << std::endl;
                break;
            }
        }
        pthread_exit(nullptr);
    }

private:
    std::queue<T *> _taskQ; // 任务队列
    int _taskSize;          // 任务数量

    pthread_t _managerID;                  // 管理线程ID
    std::vector<pthread_t> _threadIDs;     // 执行任务线程ID
    std::vector<pthread_t> _joinThreadIDs; // 要join的任务线程ID
    int _max;                              // 最大线程数
    int _min;                              // 最小线程数
    int _liveNum;                          // 存活线程数
    int _busyNum = 0;                      // 忙线程数
    int _exitNum = 0;                      // 要退出的线程数

    pthread_mutex_t _poolMutex; // 线程池锁
    pthread_mutex_t _busyMutex; // 用来锁busyNum
    pthread_cond_t _full;       // 队列满的条件变量  主线程在队列满了的时候等待  也就是在这个条件变量下进行等待  条件满足进行wait
    pthread_cond_t _empty;      // 队列空的条件变量 任务线程在队列为空的时候进行等待  也就是在这个条件变量下进行等待 条件满足进行wait

    bool _isStop = false; // 停止标志位
};